#include <stdio.h>
#include <string.h>
#include <stdint.h>

#define UNIVERSE_SIZE_Y 12
#define UNIVERSE_SIZE_X 24
#define GLOBAL /**/
#define ALIVE 1
#define DEAD 0

GLOBAL int8_t UNIVERSE[UNIVERSE_SIZE_Y][UNIVERSE_SIZE_X];

int count_neighbours(int x, int y);
void fill_universe(void);
void print_universe(void);
void next_generation(void);

int main(int argc, char *argv[]){
  uint64_t gen = 1;
  
  fill_universe();
  
  //configuration
  UNIVERSE[4][5] = ALIVE;
  UNIVERSE[3][6] = ALIVE;
  UNIVERSE[4][6] = ALIVE;
  UNIVERSE[4][7] = ALIVE;
  
  print_universe();
  
  while (1){
    printf("Generation %li\n", gen);
    getchar();
    next_generation();
    gen++;
    print_universe();
  }
  
  return 0;
}

void next_generation(void){
  int8_t buffer[UNIVERSE_SIZE_Y][UNIVERSE_SIZE_X];
  int y, x, neighbours;
  
  for (y=0; y != UNIVERSE_SIZE_Y; y++)
    for (x=0; x != UNIVERSE_SIZE_X; x++)
      buffer[y][x] = DEAD;
  
  for (y=0; y != UNIVERSE_SIZE_Y; y++)
    for (x=0; x != UNIVERSE_SIZE_X; x++){
      neighbours = count_neighbours(y,x);
      if ((UNIVERSE[y][x] && neighbours == 2) || (UNIVERSE[y][x] && neighbours == 3))
	    buffer[y][x] = ALIVE;
      else if ((UNIVERSE[y][x] && neighbours < 2) || (UNIVERSE[y][x] && neighbours > 3))
	    buffer[y][x] = DEAD;
      if (!UNIVERSE[y][x] && neighbours == 3)
	buffer[y][x] = ALIVE;
    }
  for (y=0; y != UNIVERSE_SIZE_Y; y++)
    for (x=0; x != UNIVERSE_SIZE_X; x++)
      UNIVERSE[y][x] = buffer[y][x];
}

int count_neighbours(int y, int x){
  int i, j;
  int neighbours = 0;
  
  for (i=y-1;i<=y+1;i++)
    for (j=x-1;j<=x+1;j++){
      if (i < 0 || i >= UNIVERSE_SIZE_Y) continue;
      else if (j < 0 || j >= UNIVERSE_SIZE_X) continue;
      else if (UNIVERSE[i][j] == ALIVE) neighbours++;
    }
  if (UNIVERSE[y][x] == ALIVE) neighbours--;
  return neighbours;
}

void print_universe(void){
  int x,y;
  
  for (y=0; y != UNIVERSE_SIZE_Y; y++){
    for (x=0; x != UNIVERSE_SIZE_X; x++)
      printf("%i",UNIVERSE[y][x]);
    putchar('\n');
  }
  putchar('\n');
}

void fill_universe(void){
  int x,y;
  
  for (y=0; y != UNIVERSE_SIZE_Y; y++)
    for (x=0; x != UNIVERSE_SIZE_X; x++)
      UNIVERSE[y][x] = DEAD;
}
